#include <stdio.h>
#include <stdbool.h>
#include <alsa/asoundlib.h>

// 设置音频采集开关的函数
// card: 声卡名称
// selem: 控制项名称
// enable: 开关状态
int set_capture_switch(const char* card, const char* selem, bool enable) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 设置采集开关（启用或禁用）
    if ((err = snd_mixer_selem_set_capture_switch_all(elem, enable ? 1 : 0)) < 0) {
        fprintf(stderr, "Unable to set capture switch: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return 0; // 成功
}

// 设置音频回放开关的函数
// card: 声卡名称
// selem: 控制项名称
// enable: 开关状态
int set_playback_switch(const char* card, const char* selem, bool enable) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 设置回放开关（启用或禁用）
    if ((err = snd_mixer_selem_set_playback_switch_all(elem, enable ? 1 : 0)) < 0) {
        fprintf(stderr, "Unable to set playback switch: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return 0; // 成功
}

// 获取音频采集音量
// card: 声卡名称
// selem: 控制项名称
// 返回值: 当前音量
int get_capture_volume(const char* card, const char* selem)
{
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取采集通道音量
    long volume = 0;
    if ((err = snd_mixer_selem_get_capture_volume(elem, 0, &volume)) < 0) {
        fprintf(stderr, "Unable to get capture volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功返回音量
}

// 获取音频回放通道音量
// card: 声卡名称
// selem: 控制项名称
// 返回值: 当前音量
int get_playback_volume(const char* card, const char* selem) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取回放通道音量
    long volume = 0;
    if ((err = snd_mixer_selem_get_playback_volume(elem, 0, &volume)) < 0) {
        fprintf(stderr, "Unable to get playback volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功返回音量
}

// 设置音频采集音量
// card: 声卡名称
// selem: 控制项名称
// volume: 设置音量
// 返回值: 成功返回设置后的音量，失败返回错误码
int set_capture_volume(const char* card, const char* selem, long volume)
{
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取音量范围
    long min, max;
    if ((err = snd_mixer_selem_get_capture_volume_range(elem, &min, &max)) < 0)
    {
        fprintf(stderr, "Unable to get capture volume range: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }
    
    if (volume < min)
    {
        volume = min;
    }

    if (volume > max)
    {
        volume = max;
    }

    // 设置采集通道音量
    if ((err = snd_mixer_selem_set_capture_volume_all(elem, volume)) < 0) {
        fprintf(stderr, "Unable to set capture volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功
}

// 设置音频回放通道音量
// card: 声卡名称
// selem: 控制项名称
// volume: 设置音量
// 返回值: 成功返回设置后的音量，失败返回错误码
int set_playback_volume(const char* card, const char* selem, long volume)
{
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取音量范围
    long min, max;
    if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max)) < 0)
    {
        fprintf(stderr, "Unable to get playback volume range: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    if (volume < min)
    {
        volume = min;
    }

    if (volume > max)
    {
        volume = max;
    }

    // 设置回放通道音量
    if ((err = snd_mixer_selem_set_playback_volume_all(elem, volume)) < 0) {
        fprintf(stderr, "Unable to set playback volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功返回设置后音量
}

int main(int argc, char** argv)
{
    printf("Playback Vol: %d\n", get_playback_volume("hw:0", "Analog"));
    printf("New Playback Vol: %d\n", set_playback_volume("hw:0", "Analog", atoi(argv[1])));

    return 0;
}